#include "EPollPoller.h"
#include "Logger.h"
#include "Channel.h"

#include <errno.h>
#include <unistd.h>
#include <string.h>

//channel还没添加到poller
const int kNew = -1; //chaannel的成员index_ = -1,这三个与index_相对应
//已经添加
const int kAdded = 1;
//已经删除
const int kDeleted = 2;

EPollPoller::EPollPoller(EventLoop* Loop)
    : Poller(Loop)
    , epollfd_(::epoll_create1(EPOLL_CLOEXEC))
    , events_(kInitEventlistSize) //vector<epoll_event>
{
    if (epollfd_ < 0 )
    {
        LOG_FATAL("epoll_create error:%d\n",errno);
    }
}
EPollPoller::~EPollPoller() 
{
    close(epollfd_);
}

//在epoll中xdyepoll_wait
Timestamp EPollPoller::poll(int timeoutMs, ChannelList* activeChannels)
{
    LOG_INFO("func=%s => fd total count=%zu \n", __FUNCTION__, channels_.size());

    //迭代器与指针有相似之处，但它们并不完全相同。
    int numEvents = ::epoll_wait(epollfd_, &*events_.begin(),static_cast<int>(events_.size()),timeoutMs);
    int saveErrno = errno;
    //定义当前时间
    Timestamp now(Timestamp::now());
    if(numEvents > 0)
    {
        LOG_INFO("%d events happened \n", numEvents);
        fillActiveChannels(numEvents,activeChannels);
        if(numEvents == events_.size())
        {
            events_.resize(events_.size()*2);
        }
    }
    else if(numEvents == 0)
    {
        LOG_DEBUG("%s timeout! \n", __FUNCTION__);
    }
    else
    {
        //如果不是由于外部中段而发生错误
        if(saveErrno != EINTR)
        {
            errno = saveErrno;
            LOG_ERROR("EPollPoller::poll() err!");
        }
    }
    return now;
}

//channel update remove=>EventLoop=>Poller updateChannel removeChannel
/**
 *          EventLoop
 * ChannelList     Poller
 *                ChannelMap <fd, channel*> epollfd
*/
void EPollPoller::updateChannel(Channel* channel) 
{
    const int index = channel->index();
    LOG_INFO("func=%s => fd=%d events=%d index=%d \n", __FUNCTION__, channel->fd(),channel->events(),index);
    if(index == kNew || index == kDeleted)
    {
        if(index == kNew)
        {
            int fd = channel->fd();
            channels_[fd] = channel;
        }

        channel->set_index(kAdded);
        update(EPOLL_CTL_ADD, channel);
    }
    else //channel已经在poller上注册过了
    {
        int fd = channel->fd();
        if(channel->isNoneEvent())
        {
            update(EPOLL_CTL_DEL, channel);
            channel->set_index(kDeleted);
        }
        else
        {
            update(EPOLL_CTL_MOD, channel);
        }
    }

}

//从poller中删除channel
void EPollPoller::removeChannel(Channel* channel) 
{
    int fd = channel->fd();
    //从poller中删除
    channels_.erase(fd);
    
    LOG_INFO("func=%s => fd=%d \n", __FUNCTION__, fd);
    int index = channel->index();
    //如果在epoll中注册过就要从epoll中删除
    if(index == kAdded)
    {
        update(EPOLL_CTL_DEL,channel);
    }
    channel->set_index(kNew);
}


void EPollPoller::fillActiveChannels(int numbers,ChannelList* activeChannels) const
{
    for(int i = 0; i < numbers; i++)
    {
        Channel* channel = static_cast<Channel*>(events_[i].data.ptr);
        channel->set_revents(events_[i].events);
        activeChannels->push_back(channel); //EventLoop就拿到了它的poller给它返回的所有发生事件的channel列表了
    }
}

//更新channel，相当于epoll_ctl add/mod/del
void EPollPoller::update(int operation, Channel* channel)
{
    epoll_event event;
    memset(&event, 0, sizeof(event));

    int fd = channel->fd();

    event.events = channel->events();
    event.data.fd = fd;
    event.data.ptr = channel;

    if(::epoll_ctl(epollfd_, operation, fd, &event) < 0)
    {
        if(operation == EPOLL_CTL_DEL)
        {
            LOG_INFO("epoll_ctl del error:%d\n", errno);
        }
        else
        {
            LOG_FATAL("epoll_ctl add/mod error:%d\n", errno);
        }
    }
}